`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    18:40:18 04/14/2014 
// Design Name: 
// Module Name:    Vigenere 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module Vigenere_dec(
    key,
    data_in,
    data_out,
	 clk
    );
	
	input [127:0] key;
	input [127:0] data_in;
	output [127:0] data_out;
	input clk;
	
	wire [7:0] rom_out_blocks [15:0];
	reg [6:0] address_blocks [15:0];
	wire [7:0] key_blocks [15:0];
	wire [7:0] data_in_blocks [15:0];
	reg [4:0] j = 0;
	wire [8:0] accumulators [15:0];
	
	generate
	genvar i;
		for (i = 0; i < 16; i = i + 1)
		begin: romgen
			ROM_95x8 ROM(
				.addr(address_blocks[i]),
				.data_out(rom_out_blocks[i])
			);
			
			assign key_blocks[i] = key[(i*8)+7:(i*8)];
			assign data_in_blocks[i] = data_in[(i*8)+7:(i*8)];
			assign accumulators[i] = key_blocks[i] - data_in_blocks[i];
			assign data_out[(i*8)+7:(i*8)] = rom_out_blocks[i];
		end
	endgenerate
	
	always @(posedge clk)
	begin
		for (j = 0; j < 16; j = j + 1)
		begin
			if (accumulators[j][8] == 1'b1)	// is negative
			begin
				address_blocks[j] = ~accumulators[j] + 1;
			end				
			else if (accumulators[j] == 0)
				address_blocks[j] = accumulators[j];
			else
				// take absolute value by inverting then adding 1 (two's complement)
				address_blocks[j] = ~(accumulators[j] - 95) + 1;
		end
	end
	
endmodule
